#include "server.h"

static int socketfd = -1;
static int client_fd = -1;

int huminity = 0;
int temperature = 0;

void Send_Msg(int fd, Package_t pack)
{
    int size = write(fd, &pack, sizeof(pack));
    if(size <= 0)
    {
        printf("send fail\n");
    }

    return ;
}

static void *Recv_Msg(void *arg)
{
    pthread_detach(pthread_self());

    User_t *tmp = (User_t *)arg;

    User_t user;
    memset(&user, 0, sizeof (user));
    user.fd = tmp->fd;
    user.port = tmp->port;
    memcpy(user.ip, tmp->ip, strlen(tmp->ip));
   // printf("--tid=%lx-----ip:%s,port:%d, fd=%d\n", pthread_self(), user.ip, user.port, user.fd);

    Package_t pack;
    while(1)
    {
        memset(&pack, 0, sizeof(Package_t));
        int ret = read(user.fd, (void *)&pack, sizeof(Package_t));
        if(ret <= 0)
        {
            printf("one exits\n");
            close(user.fd);
            pthread_exit(NULL);
            return NULL;
        }
        printf("cmd : %d\n", pack.cmd);
        switch (pack.cmd)
        {
            case DELETE:
            {
                deleteFile(pack.data);
                break;
            }
            case POST:
            {
                recv_file(user.fd, pack.data);
                break;
            }
            case GET:
            {
                send_file(user.fd, pack.data);
                break;
            }
            case SINGLE:
            {
				#if 1
				// 使用sscanf函数解析字符串
				if (sscanf(pack.data, "@%d:%d", &huminity, &temperature) == 2) {
					// 解析成功，输出h和t的值
					printf("h: %d, t: %d\n", huminity, temperature);
				} else {
					printf("解析失败\n");
				}
				#endif
				#if 0
                QString tmp = pack.data;
                QRegularExpression re("[@:$]");

                // 使用正则表达式切割字符串
                QStringList list = tmp.split(re, Qt::SkipEmptyParts);
                huminity = list.at(0).toInt();
                temperature = list.at(1).toInt();
				#endif
            }
            break;
            default:
                printf("others\n");
                break;
        }
    }
 }

static void *init(void *arg)
{
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if(socketfd < 0)
    {
        perror("socket fail\n");
        return NULL;
    }

    struct sockaddr_in myaddr;
    memset(&myaddr, 0, sizeof(myaddr));
    myaddr.sin_family       = AF_INET;
    myaddr.sin_port         = htons(PORT_TCP);
    myaddr.sin_addr.s_addr  = INADDR_ANY;

    //2.开启复用
    int on=1; //开启  SO_REUSEPORT
    int ret = setsockopt(socketfd,SOL_SOCKET, SO_REUSEADDR,&on,sizeof(on));
    if(ret < 0)
    {
        perror("setsockopt fail\n");
        return NULL;
    }

    ret = bind(socketfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in));
    if(ret < 0)
    {
        perror("bind fail\n");
        return NULL;
    }
    ret = listen(socketfd, 5);
    if(ret < 0)
    {
        close(socketfd);
        return NULL;
    }

    struct sockaddr_in client_addr;
    int len = sizeof(struct sockaddr);

    while(1)
    {
        //qDebug("---accepting---\n");
        memset(&client_addr, 0, sizeof(client_addr));
        client_fd = ::accept(socketfd,(struct sockaddr *)&client_addr, (socklen_t*)&len);
        if(client_fd < 0)
        {
            perror("accept fail\n");
            return NULL;
        }
        else
        {
            printf("accept\n");

            User_t user;
            memset(&user, 0, sizeof(user));
            user.fd = client_fd;
            user.port = ntohs(client_addr.sin_port);
            memcpy(user.ip, inet_ntoa(client_addr.sin_addr), strlen(inet_ntoa(client_addr.sin_addr)));

            pthread_t tid = 0;
            pthread_create(&tid, NULL, Recv_Msg, (void *)&user);
        }
    }
}

int init_server()
{
    pthread_t tid = 0;
    pthread_create(&tid, NULL, init, NULL);
}

void logout()
{
    ::close(socketfd);
}

void single_send(int fd,  char *data)
{
    Package_t pack;
    memset(&pack, 0, sizeof(pack));
    pack.cmd = SINGLE;
    memcpy(pack.data, data, strlen(data));

    write(fd, &pack, sizeof (pack));
}

void group_send(int fd, char *data)
{
}

void recv_file(int socket, char *data)
{
    cJSON *root = cJSON_Parse(data);
    if(root == NULL)
    {
        printf("get root fail!!!\n");
        return ;
    }

    std::string path = "tts_sample.wav";//cJSON_GetObjectItem(root,"file")->valuestring;
    int size = cJSON_GetObjectItem(root,"size")->valueint;
    //std::string path = cJSON_GetObjectItem(root,"path")->valuestring;
    //path = PATH + path;

    printf("file : %s  size=%d\n", path.c_str(), size);
    printf(": %s\n", path.c_str());
    int  fd = open(path.c_str(), O_RDWR|O_CREAT, 666);//
    if(fd < 0)
    {
        perror("open fail\n");
        cJSON_Delete(root);
        return ;
    }
    cJSON_Delete(root);

    int progress = 0;
    char buf[1024] = {0};
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        int ret = read(socket, buf, sizeof (buf));
        if(ret <= 0)
        {
            close(fd);
            break;
        }
        write(fd, buf,ret);
        progress += ret;

        //qDebug("进度：%d\n",progress*100/size);
        if(progress >= size)
        {
            close(fd);
            break;
        }
    }
    //qDebug() << "end";

    system("./ShiBie");
    referFile();
}

void send_file(int socket, char *file)
{
    int  fd = open(file, O_RDWR);
    if(fd < 0)
    {
        perror("open fail\n");
        welog_debug("上传失败：文件不存在\n");
        return ;
    }

    //获取文件大小
    off_t size = lseek(fd, 0, SEEK_END);
    if(size <= 0)
    {
        welog_debug("上传失败：too small\n");
        close(fd);
        return ;
    }

    Package_t pack;
    memset(&pack, 0, sizeof(pack));
    pack.cmd = GET;

    cJSON *root = cJSON_CreateObject();
    cJSON_AddItemToObject(root,"file",cJSON_CreateString(file));
    cJSON_AddItemToObject(root,"size",cJSON_CreateNumber(size));
    cJSON_AddItemToObject(root,"path",cJSON_CreateString("."));
    char *json_data = cJSON_Print(root);
    sprintf(pack.data, "%s", json_data);
    cJSON_Delete(root);

    write(socket, &pack, sizeof(pack));

    lseek(fd, 0, SEEK_SET);

    int ret = 0;
    long total = 0;
    char buf[1024] = {0};
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        ret = read(fd,buf,1024);
        total += ret;
        if(ret < 0)
        {
            perror("读取失败\n");
            break;
        }
        else if(ret >= 0)
        {
            //welog_debug("progress = %ld%%\n", total*100/size);
            ret = write(socket, buf, ret);
            if(ret <= 0)
            {
                welog_debug("send fail\n");
                break;
            }
        }
        if(total>=size)
            break;
    }
    close(fd);
    //qDebug() << "end";
}

#include <sstream>

template<typename T>
std::string to_string_custom(T value) {
    std::ostringstream oss;
    oss << value;
    return oss.str();
}

void referFile()
{
	#if 0
    QFile file("1.txt");
    if (!file.open(QIODevice::ReadOnly )) {
        //qDebug() << "无法打开XML文件";
        return ;
    }

    QString data = file.readAll();
//qDebug() << data;
    // 关闭文件
    file.close();
#endif
	std::string data = "";

	FILE *file;
    char buffer[1024];

    // 打开文件
    file = fopen("1.txt", "r");

    if (file == NULL) {
        perror("无法打开文件。\n");
        return ;
    }

    // 读取文件内容
    while (fgets(buffer, sizeof(buffer), file) != NULL) 
	{
        data.append(buffer);
    }

    // 关闭文件
    fclose(file);

#if 1
    //if(data.contains("温度"))
		printf("data=%s\n", data.c_str());
	if(data.find("温度") != std::string::npos)
    {
        //qDebug() << "温度";
        std::string cmd = "./Hecheng 当前温度为" +  to_string_custom(temperature) + "℃";
        system(cmd.c_str());
        send_file(client_fd, (char *)"tts_sample.wav");
    }
	else if(data.find("湿度") != std::string::npos)
    //else if(data.contains("湿度"))
    {
        //qDebug() << "湿度";
        std::string cmd = "./Hecheng 当前湿度为" +  to_string_custom(huminity) + "%";
        system(cmd.c_str());
        send_file(client_fd, (char *)"tts_sample.wav");
    }
	else if(data.find("开灯") != std::string::npos)
    //else if(data.contains("开灯"))
    {
        //qDebug() << "L_ON";
        single_send(client_fd,  (char *)"L_ON");
    }
	else if(data.find("关灯") != std::string::npos)
    //else if(data.contains("关灯"))
    {
        //qDebug() << "L_OFF";
        single_send(client_fd,  (char *)"L_OFF");
    }
	else if(data.find("打开窗帘") != std::string::npos)
    //else if(data.contains("打开窗帘"))
    {
        //qDebug() << "打开窗帘";
        single_send(client_fd,  (char *)"W_ON");
    }
	else if(data.find("关闭窗帘") != std::string::npos)
    //else if(data.contains("关闭窗帘"))
    {
        //qDebug() << "关闭窗帘";
        single_send(client_fd,  (char *)"W_OFF");
    }
	#endif
}

void deleteFile(std::string )
{
	#if 0 
    //qDebug() << data;
    QJsonParseError err;
    QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8(), &err);
    if(err.error != QJsonParseError::NoError)
    {
        //printf() << "json error";
        return;
    }
    //获取json对象
    QJsonObject obj = doc.object();
    if(!obj.isEmpty())
    {
        QString name = obj.value("file").toString();
        std::string file = (PATH + name).toStdString();
        //printf() << "delete " << file.c_str();
        system(("rm -rf \"" + file + "\"").c_str());
    }
	#endif
}

int main()
{
	init_server();
	
	while(1)
	{
		sleep(1);
	}
	
	return 0;
}